/**
 * 文件上传模块
 * 缓存临时文件，返回特定id
 * ----------------------------------------
 */

"use strict";

var fs = require('fs');
var filepath = require('path');
var radon = require('radon');
var util = radon.util;
var include = radon.use('Include');
var File = radon.use('File');
var UploadFile = include.ModelDB.model('UploadFile');
var undef;

// 检查文件上传资料是否符合要求
exports.checkUpload = function *(req, res){
	var data = req.get();
	var type = data.post.type;
	var files = data.files || [data.file];
	if (!data){
		radon.throw(100000);
	}
	var self = this;
	if (self.checkUser){
		yield self.checkUser(data);
	}

	for (var i = 0; i < files.length; i++) {
		if (!checkFileInfo.call(self, type, file)) {
			return {'pass': false};
		}
	}

	return {'pass': true};
}

// 处理文件上传, 保存到指定的临时目录
exports.doUpload = function *(req, res){
	var self = this;
	var data = req.get();
	var type = data.post.type;
	var files = data.files;
	if (self.checkUser){
		yield self.checkUser(data);
	}

	for (var i = 0; i < files.length; i++) {
		var f = files[i];
		// 检查文件信息是否符合设置要求
		var rule = checkFileInfo.call(self, type, f);
		var file = new File(f.tmpFile);
		var filename = filepath.basename(f.tmpFile);
		var info = {
			'_id': filename,
			'type': type,
			'name': f.fileName,
			'ext': f.extName,
			'path': f.tmpFile,
			'size': yield file.size()
		};

		// 检查是否有处理程序
		if (rule.handler){
			var result = yield res.request(rule.handler, info);
			// 处理程序可以修改保存的文件地址
			info.path = result.path;
			// 附加 info 到返回数据中
			if (result.info){
				info.info = result.info;
			}
			// 业务内部数据, 保存到记录中, 不返回到前端
			if (result.data){
				info.data = result.data;
			}
		}else {
			// 生成临时文件名
			info.path = (rule.tmpPath || self.getConfig('tmpPath')) + filename;
		}

		// 移动文件
		if (info.path){
			file.rename(info.path);
		}

		// 写入临时文件记录到数据库
		var m = new UploadFile(info);
		yield m.save();

		// 不返回临时路径到客户端
		info.id = info._id;
		info.path = info.data = info._id = undef;
	}

	res.setHeader('content-type', 'application/json');

	// 返回结果给客户端
	return {'code': 0, 'data': info};
}

// 保存文件到指定路径
exports.saveFile = function *(req, res){
	var data = req.get();
	if (!data.id || !data.type){
		radon.throw(100004);
	}
	var rs = yield UploadFile.findOne({
		'_id': data.id,
		'type': data.type
	});

	if (rs){
		var file = new File(rs.path);
		// 指定自动移动的文件路径
		if (data.path){
			yield file.rename(data.path);
			rs.path = data.path;
		}
		// 返回上传文件记录, 包括业务的数据
		res.reply(rs);
	}else {
		radon.throw(100005, [data.id]);
	}
}

// 检查文件信息是否符合要求设置
function checkFileInfo(type, file){
	// 判断输入参数是否正确
	if (!type || !file){
		radon.throw(100000);
	}
	// 检查是否有对应的文件类型上传配置
	var rule = this.getConfig('rules.'+type);
	if (!rule){
		radon.throw(100001, [type]);
	}

	// 截取文件扩展名
	if (file.extName === undef){
		var ext = /^.+\.([^\.]+)$/.exec(file.fileName);
		file.extName = ext ? ext[1].toLowerCase() : '';
	}
	// 判断文件类型是否允许上传
	var fileExt = file.extName || '*';
	if (rule.types.indexOf(fileExt) === -1){
		radon.throw(100003, [fileExt]);
	}

	// 检查文件大小是否超出限制
	if (rule.typeSize && rule.typeSize[fileExt]){
		if (file.size > rule.typeSize[fileExt]){
			radon.throw(100002, [readableSize(rule.typeSize[fileExt])]);
		}
	}else if (rule.maxSize > 0 && file.size > rule.maxSize) {
		radon.throw(100002, [readableSize(rule.maxSize)]);
	}

	return rule;
}

function readableSize(size){
	var m = 1<<20;
	var k = 1<<10;
	if (size > m){
		return (size >> 20) + 'MB';
	}else if (size > k){
		return (size >> 10) + 'KB';
	}else {
		return size + 'B';
	}
}